package com.maiji.cloud.service.impl;

import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.google.common.collect.Maps;
import com.maiji.cloud.entities.login.UserInfo;
import com.maiji.cloud.entities.shopingmall.ShareOrderHelpLog;
import com.maiji.cloud.entities.shopingmall.ShareOrderLog;
import com.maiji.cloud.entities.shopingmall.ShareOrderRule;
import com.maiji.cloud.entities.shopingmall.ShopingOrder;
import com.maiji.cloud.mapper.ShareOrderHelpLogMapper;
import com.maiji.cloud.microservice.UserInfoService;
import com.maiji.cloud.request.ReqMetaData;
import com.maiji.cloud.request.shopingmall.ShareOrderLogFindAllData;
import com.maiji.cloud.response.BaseDataResDto;
import com.maiji.cloud.response.BaseMetaResDto;
import com.maiji.cloud.response.ResMetaData;
import com.maiji.cloud.response.Status;
import com.maiji.cloud.response.shopingmall.ShareOrderLogResData;
import com.maiji.cloud.response.shopingmall.ShopingOrderResData;
import com.maiji.cloud.service.ShareOrderHelpLogService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.maiji.cloud.service.ShareOrderLogService;
import com.maiji.cloud.service.ShopingOrderService;
import com.maiji.cloud.utils.*;
import com.sun.org.apache.xpath.internal.operations.Bool;
import org.apache.commons.lang.BooleanUtils;
import org.eclipse.jetty.util.StringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional
public class ShareOrderHelpLogServiceImpl extends ServiceImpl<ShareOrderHelpLogMapper, ShareOrderHelpLog> implements ShareOrderHelpLogService {

    @Value("${realmName}")
    private String realmName;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private UserInfoService appUserService;
    @Autowired
    private ShareOrderLogService shareOrderLogService;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private ShopingOrderService shopingOrderService;

    @Override
    public BaseDataResDto<Double> shareOrderHelp(String solId, String userId) {
        ShareOrderLog shareOrderLog = shareOrderLogService.selectById(solId);
        if (shareOrderLog.getEndTime().before(new Date())) return new BaseDataResDto(Status.ERROR.setMessage("助力活动已结束"));
        if (shareOrderLog.getUserId().equals(userId)) return new BaseDataResDto(Status.ERROR, "不可为自己助力");
        Boolean canHelp = canHelp(userId, solId);
        if (canHelp == null) return new BaseDataResDto(Status.ERROR, "已帮该用户助力过一次");
        if (BooleanUtils.isFalse(canHelp)) return new BaseDataResDto(Status.ERROR, "今天已帮别人助力过");
        EntityWrapper<ShareOrderHelpLog> entityWrapper3 = new EntityWrapper<>();
        entityWrapper3.eq("user_id", userId);
        ShareOrderHelpLog shareOrderHelpLog3 = selectOne(entityWrapper3);
        EntityWrapper<ShareOrderHelpLog> entityWrapper4 = new EntityWrapper<>();
        entityWrapper4.eq("share_order_log_id", solId);
        Double totalHelpMoney = selectList(entityWrapper4)
                .parallelStream().map(ShareOrderHelpLog::getHelpMoney).reduce(Double.valueOf(0), (sol1, sol2) -> Arith.add(2, sol1, sol2));
        Query query = new Query(Criteria.where("type").is(CommonIntValueEnum.MONGO_RULE_TYPE_ORDER.getValue()));
        ShareOrderRule shareOrderRule = mongoTemplate.findOne(query, ShareOrderRule.class, ShareOrderRule.TABLE_NAME);
        Double maxReturnMoney = shareOrderLog.getMaxReturMoney();
        if (totalHelpMoney >= maxReturnMoney) return new BaseDataResDto(Status.ERROR, "助力金额已满");
        Double differenceMoney = Arith.subtract(2, maxReturnMoney, totalHelpMoney);
        ShareOrderHelpLog shareOrderHelpLog = new ShareOrderHelpLog().setUuId(UUID_MD5.getUUID())
                .setUserId(userId).setShareOrderLogId(solId).setHelpTime(new Date());
        if (shareOrderHelpLog3 != null) { // 老用户主力金额
            shareOrderHelpLog.setNewUser(false);
            Double maxOldUserHelpMoney = shareOrderRule.getMaxOldUserHelpMoney();
            if (differenceMoney <= maxOldUserHelpMoney) shareOrderHelpLog.setHelpMoney(differenceMoney);
            else shareOrderHelpLog.setHelpMoney(Arith.getRandomNum(shareOrderRule.getMinOldUserHelpMoney(), maxOldUserHelpMoney));
        } else { // 新用户助力金额
            shareOrderHelpLog.setNewUser(true);
            Double maxNewUserHelpMoney = shareOrderRule.getMaxNewUserHelpMoney();
            if (differenceMoney <= maxNewUserHelpMoney) shareOrderHelpLog.setHelpMoney(differenceMoney);
            else shareOrderHelpLog.setHelpMoney(Arith.getRandomNum(shareOrderRule.getMinNewUserHelpMoney(), maxNewUserHelpMoney));
        }
        UserInfo userInfo = appUserService.findUserInfoByUserId(userId);
        if (userInfo != null)  shareOrderHelpLog.setNickName(userInfo.getNickName()).setHeadUrl(userInfo.getHeadUrl());
        if (! insert(shareOrderHelpLog)) return new BaseDataResDto(Status.ERROR, "保存助力数据失败");
        shareOrderLogService.updateById(shareOrderLog.setReturMoney(NumberUtil.add(shareOrderLog.getReturMoney(), shareOrderHelpLog.getHelpMoney())));
        return new BaseDataResDto(Status.SUCCESS).setData(shareOrderHelpLog.getHelpMoney());
    }

    @Override
    public Boolean canHelp(String userId, String solId) {
        EntityWrapper<ShareOrderHelpLog> entityWrapper1 = new EntityWrapper<>();
        entityWrapper1.eq("share_order_log_id", solId);
        entityWrapper1.eq("user_id", userId);
        ShareOrderHelpLog shareOrderHelpLog1 = selectOne(entityWrapper1);
        if (shareOrderHelpLog1 != null) return null;
        EntityWrapper<ShareOrderHelpLog> entityWrapper2 = new EntityWrapper<>();
        entityWrapper2.eq("user_id", userId);
        entityWrapper2.ge("help_time", TimeUtil.getZeroTime(new Date()));
        entityWrapper2.lt("help_time", TimeUtil.getBefordayTime(new Date(),1,0));
        ShareOrderHelpLog shareOrderHelpLog2 = selectOne(entityWrapper2);
        Query query = new Query(Criteria.where("type").is(CommonIntValueEnum.MONGO_RULE_TYPE_ORDER.getValue()));
        ShareOrderRule shareOrderRule = mongoTemplate.findOne(query, ShareOrderRule.class, ShareOrderRule.TABLE_NAME);
        if (! shareOrderRule.getIsMore() && shareOrderHelpLog2 != null) return false;
        return true;
    }

    @Override
    public BaseMetaResDto<List<ShareOrderLogResData>> findAllShareOrderHelpLogs(ShareOrderLogFindAllData data, ReqMetaData metaData, String userId) {
        EntityWrapper<ShareOrderLog> entityWrapper = new EntityWrapper<>();
        if (StringUtil.isNotBlank(userId)) entityWrapper.eq("user_id", userId);
        if (StringUtil.isNotBlank(data.getOrderNo())) {
            List<String> orderIds = shopingOrderService.selectList(new EntityWrapper<ShopingOrder>()
                .like("order_no", data.getOrderNo())).parallelStream().map(ShopingOrder::getUuId).collect(Collectors.toList());
            entityWrapper.in("order_id", orderIds);
        }
        if (StringUtil.isNotBlank(data.getNickName())) {
            HashMap<String, Object> map = Maps.newHashMap();
            map.put("nickName", data.getNickName());
            List<String> userIds = userInfoService.selectList(map).parallelStream().map(UserInfo::getUserId).collect(Collectors.toList());
            if (userIds.size() > 0) entityWrapper.in("user_id", userIds);
        }
        if (data.getSettlement() != null) entityWrapper.eq("settlement", data.getSettlement());
        if (data.getSomebody() != null) {
            if (BooleanUtils.isTrue(data.getSomebody())) entityWrapper.gt("retur_money", 0);
            if (BooleanUtils.isFalse(data.getSomebody())) entityWrapper.le("retur_money", 0);
        }
        entityWrapper.eq("termination", false);
        Page<ShareOrderLog> page = shareOrderLogService.selectPage(new Page<>(metaData.getPage(), metaData.getSize()), entityWrapper);
        ResMetaData resMetaData = new ResMetaData(page.getCurrent(), page.getSize(), page.getTotal());
        List<ShareOrderLog> shareOrderLogs = page.getRecords();
        if (shareOrderLogs.size() == 0) return new BaseMetaResDto<List<ShareOrderLogResData>>(Status.SUCCESS).setResMetaData(resMetaData);
        List<String> shareOrderLogIds = shareOrderLogs.parallelStream().map(ShareOrderLog::getUuId).collect(Collectors.toList());
        Map<String, List<ShareOrderHelpLog>> helpLogsMap = selectList(new EntityWrapper<ShareOrderHelpLog>()
                .in("share_order_log_id", shareOrderLogIds)).parallelStream().collect(Collectors.groupingBy(ShareOrderHelpLog::getShareOrderLogId));
        List<ShareOrderLogResData> dataList = shareOrderLogs.parallelStream().map(shareOrderLog -> {
            ShareOrderLogResData shareOrderLogResData = new ShareOrderLogResData();
            BeanUtils.copyProperties(shareOrderLog, shareOrderLogResData);
            List<ShareOrderHelpLog> shareOrderHelpLogs = helpLogsMap.get(shareOrderLog.getUuId());
            if (shareOrderHelpLogs != null) {
                Double nowReturMoney = shareOrderHelpLogs.parallelStream().map(ShareOrderHelpLog::getHelpMoney)
                        .reduce(Double.valueOf(0), (sol1, sol2) -> Arith.add(2, sol1, sol2));
                shareOrderLogResData.setNowReturMoney(nowReturMoney);
            }
            return shareOrderLogResData.setRealmName(realmName);
        }).collect(Collectors.toList());
        List<String> orderIds = shareOrderLogs.parallelStream().map(ShareOrderLog::getOrderId).collect(Collectors.toList());
        List<ShopingOrder> shopingOrders = shopingOrderService.selectBatchIds(orderIds);
        List<ShopingOrderResData> orderList = shopingOrderService.findAllShopingOrderResDataList(shopingOrders);
        dataList = BaseService.dealWithOneToOne(dataList, "getOrderId", ShareOrderLogResData.class,
                "setOrder", orderList, "getUuId", ShopingOrderResData.class);
        return new BaseMetaResDto<List<ShareOrderLogResData>>(Status.SUCCESS).setData(dataList).setResMetaData(resMetaData);
    }

}
